/*
Brick And Blast, a crossplatform breakout game.
 Copyright (C) 2008-2010 Julien CLEMENT (andematunum@gmail.com)
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#ifndef _Ball_h_
#define _Ball_h_

/**
* file   Ball.h
* date   Ven 25 déc 2009 20:47:00 CET
* brief  TODO
*/

#include "GameObject.h"
#include "Vector2d.h"
#include <math.h>


/** TESTING ONLY */
#include <iostream>
#include <set>
using namespace std;

struct ColliderData;
class BatPart;
class Bumper;
class Edge;
class Brick;

class Ball: public GameObject {
public:
  Ball () : GameObject() {
  }
  Ball (SDL_Point& initPosition,
        SDL_TextureID initTexture,
        double velocity);
  /** Calculate next position but do not perform the move.
    * Used by the collision engine. */
  virtual void calculate_next_pixel_position ();
  /** Assign a new angle after an horizontal collision occured. */
  void collide_screen_up () {
    forces_.insert(new Vector2d(0.,-2*direction_.get_y()));
  }
  void collide_screen_down () {
    forces_.insert(new Vector2d(0.,-2*direction_.get_y()));
  }
  void collide_screen_left () {
    forces_.insert(new Vector2d(-2*direction_.get_x(), 0.));
  }
  void collide_screen_right () {
    forces_.insert(new Vector2d(-2*direction_.get_x(), 0.));
  }
  /** Set the current velocity of the ball in the real space. */
  void set_velocity (double v) {
    velocity_ = v;
    set_accel_decel(1.);
  }
  /** Get the current velocity of the ball in the real space. */
  double get_velocity () {
    return velocity_;
  }
  /** Set the accel/decel factor */
  void set_accel_decel (double v) {
    accel_decel_ = v;
  }
  double get_accel_decel () {
    return accel_decel_;
  }
  /** Set a random direction to the ball */
  void set_random_direction () {
    double angle = random() * 2.*M_PI / (double)RAND_MAX;
    set_angle(angle);
  }
  /** Set the ball direction by giving an angle in radians. */
  void set_angle (double angle) {
    direction_.set(cos(angle), sin(angle));
  }
  /** Move the ball to the specified position in the pixel space .*/
  //virtual void move_to (SDL_Point& xy);
  /** Update the ball state.
      Internally calls \sa move. */
  virtual bool update () {
    GameObject::update();
    move();
    return false;
  }
  /** Move the ball in the real space. */
  void move ();
  /** Update the direction by applying all the forces
    * to the current direction */
  void update_direction ();
  /** Manage the collision between the ball and the game area boundaries. */
  virtual bool handle_game_area_collisions ();
  void handle_collision_circle (const ColliderData& data);
  void handle_collision_rectangle (const ColliderData& data);
  void handle_collision (GameObject* obj, const ColliderData& data);
  void handle_collision (BatPart* bat, const ColliderData& data);
  void handle_collision (Edge* edge, const ColliderData& data);
  void handle_collision (Brick* brick, const ColliderData& data);

private:
  /** Position in the real space, used
      for motion physics. */
  Vector2d center_;
  /** Current direction vector */
  Vector2d direction_;
  /** Set of force vectors the ball is
    * constrained by.
    * We use a set to avoid having twice the
    * same force vector represented.
    * The next direction is calculated by
    * suming the forces to the current direction. */
  set<Vector2d*> forces_;
  /** Current velocity. */
  double velocity_;
  /** Accel/Decel */
  double accel_decel_;
};

#endif

